#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

/*
* 常见类型转换,4个字节的内存空间
*/
typedef union BYTE4_CONVERT
{
	float a_float;      //单精浮点数
	uint32_t a_unint;   //无符号整型
	int32_t a_int;      //有符号整型
	uint8_t un_bytes[4];//无符号字节型数组
	int8_t  bytes[4];   //有符号字节型数组
}byte4_conv;

/*
	* 不同的处理器架构在设计时，对字节存储顺序有不同的考量。
	* 在某些情况下，大小端模式的选择会影响内存访问效率。
	-----------------------------------
	| 处理器架构 |       字节序       |
	-----------------------------------
	| Intel x86	 | Little-Endian      |
	| Power-PC 	 |	Big-Endian        |
	| ARM	     |	默认 Little-Endian|
	| STM32		 | Little-Endian      |
	-----------------------------------
	大端（更方便地进行数据处理和传输）               小端 （更符合人类从低位到高位的运算习惯）

	                            0x12345678
	低          高                			            低          高
   -------------------               				---------------------
  | 12 | 34 | 56 | 78 |     		<->     		| 78 | 56 | 34 | 12 |
   -------------------               				---------------------

   * 大小端进行数据顺序交换
*/

void swap_union(byte4_conv* con)
{
	uint8_t buff;
	buff = con->bytes[0];
	con->bytes[0] = con->bytes[3];
	con->bytes[3] = buff;
	buff = con->bytes[1];
	con->bytes[1] = con->bytes[2];
	con->bytes[2] = buff;
}

void printf_bytes(uint8_t bytes[4])
{
	printf("-----------------\r\n");
	printf("| 0 | 1 | 2 | 3 |\r\n");
	printf("-----------------\r\n");
	printf("| %02X| %02x| %02x| %02x|\r\n", bytes[0], bytes[1], bytes[2], bytes[3]);
	printf("-----------------\r\n");
}

void byte4_conv_example(void)
{
	byte4_conv con;//定义1个联合体对象
	con.a_int = 0x11223344;
	printf("a_int = %#X\n", con.a_int);
	printf_bytes(con.un_bytes);
	swap_union(&con);
	printf_bytes(con.un_bytes);
	printf("a_int = %#X\n", con.a_int);
}

/*
* Modbus指令联合体
*/
typedef union MODBUS_COMMAND_UNION
{
	//协议定义，操作对象
	struct
	{
		uint8_t   slave_addr;//从机地址
		uint8_t   func_code; //功能码
		uint16_t  reg_addr;  //起始地址
		uint16_t  reg_len;   //地址长度
		uint16_t  crc;       //校验值
	};
	//传输数据
	uint8_t bytes[8];        
}modbus_cmd_union;

/**
请求报文（从站地址 1，起始地址 0x0000，读取 2 个寄存器）：
	01 03 00 00 00 02 00 00 (CRC)
	03：功能码（0x03 表示读保持寄存器）
	00 00：起始地址（0x0000）
	00 02：寄存器数量（2 个）

响应报文（假设寄存器值为 0x1234 和 0x5678）
	01 03 04 12 34 56 78 00 00 (CRC)
	04：数据字节数（4 字节，即 2 个寄存器 × 2 字节）
	12 34 56 78：两个寄存器的值（0x1234 和 0x5678）
*/

void modbus_example()
{
	modbus_cmd_union cmd;
	uint8_t arr[] = { 0x01,0x03,0x11,0x22,0x00,0x02,0x11,0x22 };
	//解析接收到的字节数据包
	memcpy(cmd.bytes, arr, sizeof(arr));
	printf("slave_addr: %04d\r\n", cmd.slave_addr);
	printf("func_code : %02d\r\n", cmd.func_code);
	printf("reg_addr  : %#04x\r\n", cmd.reg_addr);
	printf("regs_len  : %04d\r\n", cmd.reg_len);
	//读取地址0x08的从机的0x1122地址长度为0x2233的数据
	cmd.slave_addr = 0x08;
	cmd.func_code = 0x03;
	cmd.reg_addr = 0x1122;
	cmd.reg_len = 0x2233;
	//模拟发送的过程
	for (uint8_t i = 0;i < sizeof(cmd.bytes);i++)
		printf("%#02X,", cmd.bytes[i]);
}

int main(void)
{
	byte4_conv_example();
	modbus_example();
	return 0;
}